我们一起来推一推。
设 $f[i][j]$ 表示:现在是第 $i$ 天,手上拥有的股票数为 $j$ 时赚到的最多的钱
我们考虑转移几个方向:空手买,不买不卖,之前买过了现在继续买,买过后需要卖
空手买
空手买就是第一次买,显然不要考虑 “间隔 $w$ 天” 的限制,直接买就好。
那么很容易得到转移式:
因为是买入,所以是负数。
不买不卖
很显然可以直接从 $f[i-1][j]$ 转移过来。
转移式:
之前买过了现在继续买
很显然这次我们需要考虑 $w$ 的限制了,不过我们可以直接从 $i-w-1$ 天转移。
假设我们是从 $f[i-w-1][k]$ 转移过来的,那么这次转移我们多买了 $j-k$ 张股票,容易得到转移式:
当然因为规定了一天最多买入 $AS_i$ 股,上面的式子必须满足 $j-AS_i\leq k \leq j$
买过之后需要卖
同样的有 $w$ 的限制,但是跟上面的第三种情况没什么两样,转移式:
因为 $BS_i$ 的限制条件,上面的式子必须满足 $j\leq k \leq j+BS_i$
时间复杂度?
枚举 $i,j$ 状态就需要 $n^2$ 的复杂度,在这个基础上转移的复杂度为:
- 空手买 : $O(1)$
- 不买不卖 : $O(1)$
- 之前买过了现在继续买 :$O(n)$
- 买过之后需要卖 :$O(n)$
会发现如果加上枚举状态的复杂度,后面两个转移的总复杂度为 $O(n^3)$ !
于是考虑优化。
我们观察第三个转移式:
对于当前的 $i,j$ ,假设有 $a,b$ 作为 $k$ 的两个选项对 $f[i][j]$ 进行转移,我们算一算 $a$ 比 $b$ 优的条件是什么:
这里我们会发现 $j\times AP_i$ 跟里面的式子没有任何关系,提出来不会产生仍和影响
于是我们发现我们只需要得到最大的 $f[i-w-1][k]+k\times AP_i$ 就好了,这里我们可以用到单调队列优化DP 。
具体代码实现如下:
1 | l=1,r=0; |
因为每一个状态都只进队/出队了一次,所以可以证明时间复杂度现在变为 $O(n^2)$ 了。
第四个操作一样可以这样优化,可以尝试一下,不贴解释了。
Code:
1 |
|